package com.icehelper.hades.base.filter;

import com.google.gson.Gson;
import com.icehelper.hades.base.log.HadesLogger;
import com.icehelper.hades.base.log.LogConstant;
import com.icehelper.hades.base.log.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

@Component
public class TraceFilter implements Filter {
  public static final HadesLogger logger = HadesLogger.create(TraceFilter.class);

  @Override
  public void init(FilterConfig filterConfig) throws ServletException {}

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;

    // 验证nginx中的traceId是否存在，不存在则生成，并存放到MDC
    String traceId = req.getHeader( LogConstant.KEY_TRACE_ID);
    if(StringUtils.isEmpty(traceId)){
      traceId = LogUtil.genTraceId();
      logger.trace("generator traceId :"+ traceId);
    }else {
      LogUtil.setTraceId(traceId);
    }

    // 验证nginx中的spanId是否存在，不存在则生成，并存放到MDC
    String spanId = req.getHeader(LogConstant.KEY_SPAN_ID);
    if(StringUtils.isEmpty(spanId)){
      spanId = LogUtil.genSpanId();
      logger.trace("generator spanId :"+ spanId);
    }else {
      LogUtil.setSpanId(spanId);
    }

    // 验证流量标识
    String hintCode = req.getHeader(LogConstant.KEY_HINT_CODE);
    if(StringUtils.isEmpty(hintCode)){
      hintCode = "0";
    }
    Long hc = 0L;
    hc = Long.parseLong(hintCode);
    LogUtil.setHintCode(hc);

    // 验证透传信息
    String hintContent = req.getHeader(LogConstant.HEADER_HINT_CONTENT);
    if(!StringUtils.isEmpty(hintContent)){
      LogUtil.setHintContent(hintContent);
    }

    String paramMap = req.getParameterMap().isEmpty() ? "" : new Gson().toJson(req.getParameterMap());

    logger.addKv(LogConstant.KEY_URI,req.getRequestURI())
        .addKv(LogConstant.KEY_METHOD,req.getMethod())
        .addKv(LogConstant.KEY_CONTENT_TYPE,req.getContentType())
        .addKv(LogConstant.KEY_ARGS,paramMap).logger().dlInfo(LogConstant.DLTAG_COM_REQUEST_IN,"request in.");

    LogUtil.setUri(req.getRequestURI());
    long start = System.currentTimeMillis();
    chain.doFilter(request,response);
    long end = System.currentTimeMillis();

    metricReq(end - start, null, req.getRequestURI());
    logger.addKv(LogConstant.KEY_URI, req.getRequestURI())
        .addKv(LogConstant.KEY_PROC_TIME, String.valueOf(end-start))
        .logger().dlInfo(LogConstant.DLTAG_COM_REQUEST_OUT, "response outgoing.");

    MDC.clear();
  }

  /**
   * 发射ELK日志
   */
  private void metricReq(Long procTime, Boolean success, String uri) {
    try {
      //TODO
    } catch (Exception e) {
      logger.debug("req metric exception", e);
    }
  }

  @Override
  public void destroy(){

  }
}
